import 'dart:math';

import 'package:flutter/material.dart';
import 'package:kq_flutter_core_widget/utils/ex/math.dart';
import 'package:kq_flutter_core_widget/widgets/chart/ex/extension.dart';
import 'package:kq_flutter_core_widget/widgets/chart/axis/base/axis.dart';
import 'package:kq_flutter_core_widget/utils/ex/string_ex.dart';

import 'base/pad_base_axis_chart.dart';

/// X轴绘制器
///
/// Created by wanggaowan on 2023/9/15 10:52
class PadXAxisRender<C extends PadBaseAxisChartDelegate>
    with PadBaseXAxisRenderMixin<C> {
  PadXAxisRender({this.isDrawLabelByGridLine = true, this.xHeight = 0});

  /// 标签是否与网格线水平居中对齐，如果为false，则标签与网格中心点水平居中对齐
  final bool isDrawLabelByGridLine;

  double xHeight;
  @override
  double getXHeight() {
    return xHeight;
  }

  @override
  double onDraw(C chart, Canvas canvas, Rect rect, double gridWidth) {
    var textPaint = TextPainter(textDirection: TextDirection.ltr);
    var paint = Paint();
    var path = Path();

    // 绘制轴线
    var xAxis = chart.xAxis;
    var yAxis = chart.yAxis;

    var labelList = xAxis.labelList;
    if (labelList == null || labelList.isEmpty) {
      _drawAxisLine(chart, canvas, xAxis, paint, path, rect, 0);
      return xAxis.labelHeight ?? xAxis.labelMinHeight;
    }

    // 绘制轴线文本
    var xLineDrawStart = rect.left + xAxis.startPadding;
    double maxLabelHeight = 0;
    List<DrawInfo?> drawInfos = [];
    for (int i = 0; i < labelList.length; i++) {
      if (gridWidth > 0) {
        if (isDrawLabelByGridLine) {
          var info = drawLabelByGridLine(
              chart,
              textPaint,
              i,
              labelList,
              xAxis,
              gridWidth,
              rect.bottom,
              rect.right,
              xLineDrawStart + yAxis.lineWidth / 2);
          drawInfos.add(info);
          if (info != null && maxLabelHeight < info.height) {
            maxLabelHeight = info.height;
          }
        } else {
          var info = drawLabelByGridCenter(
              chart,
              textPaint,
              i,
              labelList,
              xAxis,
              gridWidth,
              rect.bottom,
              xLineDrawStart + yAxis.lineWidth / 2);
          drawInfos.add(info);
          if (info != null && maxLabelHeight < info.height) {
            maxLabelHeight = info.height;
          }
        }
      }

      xLineDrawStart += gridWidth;
    }

    xLineDrawStart = rect.left + xAxis.startPadding;
    _drawAxisLine(chart, canvas, xAxis, paint, path, rect,
        maxLabelHeight + xAxis.labelOffsetAxis);

    paint.color = xAxis.gridLineColor;
    paint.strokeWidth = xAxis.gridLineWidth;
    paint.style = PaintingStyle.stroke;
    var yAxisRange =
        rect.height - maxLabelHeight - xAxis.lineWidth - xAxis.labelOffsetAxis;
    var yBottom =
        rect.bottom - xAxis.lineWidth - maxLabelHeight - xAxis.labelOffsetAxis;
    for (int i = 0; i < labelList.length; i++) {
      var info = drawInfos[i];
      if (info != null) {
        _drawLabel(chart, canvas, xAxis, info, textPaint, isDrawLabelByGridLine,
            gridWidth, rect.bottom, maxLabelHeight);
      }

      if ((i > 0 || xAxis.startPadding > 0) && xAxis.gridLineWidth > 0) {
        // 绘制X轴网格线，如果xAxis.gridUseEndPadding为true，则X轴结束点实际都在Y轴最后一根轴线下面
        path.reset();
        path.moveTo(
            xLineDrawStart + yAxis.lineWidth,
            xAxis.gridUseEndPadding
                ? yBottom - yAxisRange + yAxis.endPadding
                : yBottom - yAxisRange);
        path.lineTo(xLineDrawStart + yAxis.lineWidth,
            xAxis.gridUseStartPadding ? yBottom - yAxis.startPadding : yBottom);
        if (xAxis.gridLineDash != null) {
          path = path.dashPath(xAxis.gridLineDash!);
        }
        canvas.drawPath(path, paint);
      }

      xLineDrawStart += gridWidth;
    }

    if (!isDrawLabelByGridLine && xAxis.gridLineWidth > 0) {
      // isDrawLabelByGridLine为false，此时标签与网格中心对齐，网格线要多画一条

      // 绘制X轴网格线，如果xAxis.gridUseEndPadding为true，则X轴结束点实际都在Y轴最后一根轴线下面
      path.reset();
      path.moveTo(
          xLineDrawStart + yAxis.lineWidth,
          xAxis.gridUseEndPadding
              ? yBottom - yAxisRange + yAxis.endPadding
              : yBottom - yAxisRange);
      path.lineTo(xLineDrawStart + yAxis.lineWidth,
          xAxis.gridUseStartPadding ? yBottom - yAxis.startPadding : yBottom);
      if (xAxis.gridLineDash != null) {
        path = path.dashPath(xAxis.gridLineDash!);
      }
      canvas.drawPath(path, paint);
    }

    textPaint.dispose();
    xHeight = maxLabelHeight + xAxis.labelOffsetAxis;
    return maxLabelHeight + xAxis.labelOffsetAxis;
  }

  void _drawAxisLine(C chart, Canvas canvas, BaseXAxis xAxis, Paint paint,
      Path path, Rect rect, double maxLabelHeight) {
    if (xAxis.lineWidth > 0) {
      paint.color = xAxis.lineColor;
      paint.strokeWidth = xAxis.lineWidth;
      paint.style = PaintingStyle.stroke;
      var y = rect.bottom - maxLabelHeight - xAxis.lineWidth / 2;
      path.moveTo(chart.canScroll ? 0 : rect.left, y); // 如果可滚动从0开始，否则是rect.left
      path.lineTo(rect.right, y);
      if (xAxis.lineDash != null) {
        path = path.dashPath(xAxis.lineDash!);
      }
      canvas.drawPath(path, paint);
    }
    xAxis.$drawRect = Rect.fromLTRB(
        rect.left,
        rect.bottom - maxLabelHeight - xAxis.lineWidth,
        rect.right,
        rect.bottom - maxLabelHeight);
  }

  /// 绘制标签，内容与网格中点水平居中对齐
  @protected
  DrawInfo? drawLabelByGridCenter(
      C chart,
      TextPainter textPaint,
      int index,
      List<Label> labels,
      BaseXAxis xAxis,
      double gridWidth,
      double bottom,
      double xLineDrawStart) {
    // 绘制x轴文本
    var label = labels[index];
    var text = label.value;
    if (text.isNullOrEmpty || label.weight <= 0) {
      return null;
    }

    var maxWidth = gridWidth * label.weight - xAxis.labelHorizontalPadding;
    if (maxWidth <= 0) {
      // 文本绘制空间没有
      return null;
    }

    var labelAlign = xAxis.labelAlign;
    var overAlign = xAxis.labelOverAlign;
    textPaint.text = TextSpan(
      text: text,
      style: TextStyle(
          fontSize: xAxis.labelTextSize,
          color: xAxis.labelColor,
          overflow: xAxis.textOverflow),
    );
    textPaint.maxLines = xAxis.labelMaxLines;
    textPaint.textAlign = labelAlign;
    textPaint.ellipsis =
        xAxis.textOverflow == TextOverflow.ellipsis ? kEllipsis : null;

    textPaint.layout(minWidth: maxWidth, maxWidth: maxWidth);
    var height = xAxis.labelHeight ?? textPaint.height;
    if (xAxis.labelMaxLines > 1 &&
        overAlign != labelAlign &&
        textPaint.computeLineMetrics().length > 1) {
      textPaint.textAlign = overAlign;
      textPaint.layout(minWidth: maxWidth, maxWidth: maxWidth);
      height = xAxis.labelHeight ?? textPaint.height;
    }

    var overWidthHalf = (maxWidth - gridWidth) / 2;
    var tempRectF = Rect.fromLTRB(
        xLineDrawStart - overWidthHalf,
        bottom - _maxLabelHeight(xAxis, height),
        xLineDrawStart + gridWidth + overWidthHalf,
        bottom);
    return _getLabelMaxHeight(
        chart, xAxis, tempRectF, textPaint, xLineDrawStart);
  }

  DrawInfo _getLabelMaxHeight(C chart, BaseXAxis xAxis, Rect rect,
      TextPainter textPaint, double xLineDrawStart) {
    var labelRotation = xAxis.labelRotation;
    if (labelRotation == 0) {
      return DrawInfo(textPaint.plainText, rect.left, rect.right, rect.height,
          rect.width, textPaint.textAlign, xLineDrawStart);
    }

    double width = rect.width;
    var sv = abs(sin(labelRotation));
    textPaint.layout(maxWidth: width);
    double height;
    if (sv == 0) {
      height = rect.height;
    } else {
      height = textPaint.width * sv + rect.height * abs(cos(labelRotation));
    }

    var padding = chart.chartState?.widget.padding;
    var left = padding?.left ?? 0;
    var right = padding?.right ?? 0;
    return DrawInfo(textPaint.plainText, -left, chart.size.width + right,
        height, rect.width, textPaint.textAlign, xLineDrawStart);
  }

  void _drawLabel(
      C chart,
      Canvas canvas,
      BaseXAxis xAxis,
      DrawInfo info,
      TextPainter textPaint,
      bool centerFollowLine,
      double gridWidth,
      double bottom,
      double maxHeight) {
    var labelRotation = xAxis.labelRotation;
    var rect = Rect.fromLTRB(info.left, bottom - maxHeight, info.right, bottom);
    textPaint.text = TextSpan(
      text: info.label,
      style: TextStyle(
          fontSize: xAxis.labelTextSize,
          color: xAxis.labelColor,
          overflow: xAxis.textOverflow),
    );
    textPaint.maxLines = xAxis.labelMaxLines;
    textPaint.textAlign = info.textAlign;
    textPaint.ellipsis =
        xAxis.textOverflow == TextOverflow.ellipsis ? kEllipsis : null;

    if (labelRotation == 0) {
      if (xAxis.textOverflow != TextOverflow.visible) {
        canvas.save();
        canvas.clipRect(rect);
      }

      textPaint.layout(
          minWidth: info.textMaxWidth, maxWidth: info.textMaxWidth);
      textPaint.paint(canvas, Offset(rect.left, rect.top));

      if (xAxis.textOverflow != TextOverflow.visible) {
        canvas.restore();
      }
      return;
    }

    textPaint.layout(maxWidth: info.textMaxWidth);
    canvas.save();
    canvas.clipRect(Rect.fromLTRB(
        info.left, rect.bottom - maxHeight, info.right, rect.bottom));
    canvas.translate(info.xIndex + (centerFollowLine ? 0 : gridWidth / 2),
        rect.bottom - maxHeight);
    canvas.rotate(labelRotation);
    if (xAxis.textOverflow != TextOverflow.visible) {
      canvas.clipRect(Rect.fromLTWH(0, 0, info.textMaxWidth, info.height));
    }

    textPaint.paint(canvas, Offset.zero);
    canvas.restore();
  }

  /// 绘制标签，内容与网格线水平居中对齐
  @protected
  DrawInfo? drawLabelByGridLine(
      C chart,
      TextPainter textPaint,
      int index,
      List<Label> labels,
      BaseXAxis xAxis,
      double gridWidth,
      double bottom,
      double end,
      double xLineDrawStart) {
    // 绘制x轴文本
    var label = labels[index];
    var text = label.value;

    if (text.isNullOrEmpty || label.weight <= 0) {
      return null;
    }

    var maxWidth = gridWidth * label.weight - xAxis.labelHorizontalPadding;
    if (maxWidth <= 0) {
      // 文本绘制空间没有
      return null;
    }

    textPaint.text = TextSpan(
      text: text,
      style: TextStyle(
          fontSize: xAxis.labelTextSize,
          color: xAxis.labelColor,
          overflow: xAxis.textOverflow),
    );
    textPaint.maxLines = xAxis.labelMaxLines;
    textPaint.ellipsis =
        xAxis.textOverflow == TextOverflow.ellipsis ? kEllipsis : null;

    Rect tempRect;
    if (index == 0) {
      tempRect = parseStartIndexRect(
          chart, xAxis, textPaint, maxWidth, xLineDrawStart, bottom, end);
    } else if (index == labels.length - 1) {
      tempRect =
          parseEndIndexRect(chart, xAxis, textPaint, maxWidth, bottom, end);
    } else {
      var widthHalf = maxWidth / 2;
      textPaint.textAlign = xAxis.labelAlign;
      var textHeight = xAxis.labelHeight;
      double labelHeight;
      if (xAxis.labelMaxLines > 1 && xAxis.labelOverAlign != xAxis.labelAlign) {
        textPaint.layout(minWidth: maxWidth, maxWidth: maxWidth);
        labelHeight = textHeight ?? textPaint.height;
        if (textPaint.computeLineMetrics().length > 1) {
          textPaint.textAlign = xAxis.labelOverAlign;
        }
      } else if (textHeight == null) {
        textPaint.layout(minWidth: maxWidth, maxWidth: maxWidth);
        labelHeight = textPaint.height;
      } else {
        labelHeight = textHeight;
      }

      tempRect = Rect.fromLTRB(
          xLineDrawStart - widthHalf,
          bottom - _maxLabelHeight(xAxis, labelHeight),
          xLineDrawStart + widthHalf,
          bottom);
    }

    return _getLabelMaxHeight(
        chart, xAxis, tempRect, textPaint, xLineDrawStart);
  }

  /// 解析起始坐标文本绘制的范围
  @protected
  Rect parseStartIndexRect(
    C chart,
    BaseXAxis xAxis,
    TextPainter textPaint,
    double maxWidth,
    double xLineDrawStart,
    double bottom,
    double end,
  ) {
    var centerX = xLineDrawStart;
    var widthHalf = maxWidth / 2;
    var paddingLeft = chart.chartState?.widget.padding?.left ?? 0;
    var leftWidth = xLineDrawStart + paddingLeft;

    var labelAlign = xAxis.labelAlign;
    var overAlign = xAxis.labelOverAlign;
    var textHeight = xAxis.labelHeight;

    Rect tempRect;
    // 起始点标签绘制宽度是否与中间标签宽度一致
    double maxTextWidth;
    double labelHeight;
    if (leftWidth < widthHalf) {
      maxTextWidth = widthHalf + leftWidth;
      if (labelAlign == TextAlign.center) {
        // 与轴线中心对齐
        widthHalf = leftWidth;

        textPaint.layout(minWidth: widthHalf * 2, maxWidth: widthHalf * 2);
        labelHeight = textPaint.height;
        if (textPaint.computeLineMetrics().length > 1) {
          if (xAxis.labelMaxLines > 1) {
            textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
            if (textPaint.computeLineMetrics().length > 1) {
              textPaint.textAlign = overAlign;
              if (overAlign == TextAlign.center) {
                tempRect = Rect.fromLTRB(
                    centerX - widthHalf,
                    bottom - _maxLabelHeight(xAxis, textHeight ?? labelHeight),
                    centerX + widthHalf,
                    bottom);
              } else {
                if (textHeight == null) {
                  var width = leftWidth + maxWidth / 2;
                  textPaint.layout(minWidth: width, maxWidth: width);
                  labelHeight = textPaint.height;
                } else {
                  labelHeight = textHeight;
                }

                tempRect = Rect.fromLTRB(
                    centerX - leftWidth,
                    bottom - _maxLabelHeight(xAxis, labelHeight),
                    centerX + maxWidth / 2,
                    bottom);
              }
            } else {
              // 居中时可用宽度超出一行但是非居中可用宽度没都超出一行，
              // 此时对齐方式使用靠左对齐，因为此标签为起始标签
              textPaint.textAlign = TextAlign.left;
              if (textHeight == null) {
                var width = leftWidth + maxWidth / 2;
                textPaint.layout(minWidth: width, maxWidth: width);
                labelHeight = textPaint.height;
              } else {
                labelHeight = textHeight;
              }

              tempRect = Rect.fromLTRB(
                  centerX - leftWidth,
                  bottom - _maxLabelHeight(xAxis, labelHeight),
                  centerX + maxWidth / 2,
                  bottom);
            }
          } else {
            textPaint.textAlign = TextAlign.left;
            if (textHeight == null) {
              var width = leftWidth + maxWidth / 2;
              textPaint.layout(minWidth: width, maxWidth: width);
              labelHeight = textPaint.height;
            } else {
              labelHeight = textHeight;
            }

            tempRect = Rect.fromLTRB(
                centerX - leftWidth,
                bottom - _maxLabelHeight(xAxis, labelHeight),
                centerX + maxWidth / 2,
                bottom);
          }
        } else {
          textPaint.textAlign = labelAlign;
          tempRect = Rect.fromLTRB(
              centerX - widthHalf,
              bottom - _maxLabelHeight(xAxis, textHeight ?? labelHeight),
              centerX + widthHalf,
              bottom);
        }
      } else if (overAlign == TextAlign.center && xAxis.labelMaxLines > 1) {
        textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
        if (textPaint.computeLineMetrics().length > 1) {
          textPaint.textAlign = overAlign;
          if (leftWidth < widthHalf) {
            widthHalf = leftWidth;
          }

          if (textHeight == null) {
            var width = widthHalf * 2;
            textPaint.layout(minWidth: width, maxWidth: width);
            labelHeight = textPaint.height;
          } else {
            labelHeight = textHeight;
          }

          tempRect = Rect.fromLTRB(
              centerX - widthHalf,
              bottom - _maxLabelHeight(xAxis, labelHeight),
              centerX + widthHalf,
              bottom);
        } else {
          // 居中时可用宽度超出一行但是非居中可用宽度没都超出一行，
          // 此时对齐方式使用靠左对齐，因为此标签为起始标签
          textPaint.textAlign = labelAlign;
          tempRect = Rect.fromLTRB(
              centerX - leftWidth,
              bottom - _maxLabelHeight(xAxis, textHeight ?? textPaint.height),
              centerX + maxWidth / 2,
              bottom);
        }
      } else {
        textPaint.textAlign = xAxis.labelAlign;
        if (xAxis.labelMaxLines > 1 && overAlign != labelAlign) {
          textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
          labelHeight = textHeight ?? textPaint.height;
          if (textPaint.computeLineMetrics().length > 1) {
            textPaint.textAlign = overAlign;
          }
        } else if (textHeight == null) {
          textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
          labelHeight = textPaint.height;
        } else {
          labelHeight = textHeight;
        }

        tempRect = Rect.fromLTRB(
            centerX - leftWidth,
            bottom - _maxLabelHeight(xAxis, labelHeight),
            centerX + maxWidth / 2,
            bottom);
      }
    } else {
      maxTextWidth = maxWidth;
      textPaint.textAlign = xAxis.labelAlign;
      if (xAxis.labelMaxLines > 1 && overAlign != labelAlign) {
        textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
        labelHeight = textHeight ?? textPaint.height;
        if (textPaint.computeLineMetrics().length > 1) {
          textPaint.textAlign = overAlign;
        }
      } else if (textHeight == null) {
        textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
        labelHeight = textPaint.height;
      } else {
        labelHeight = textHeight;
      }
      tempRect = Rect.fromLTRB(
          centerX - widthHalf,
          bottom - _maxLabelHeight(xAxis, labelHeight),
          centerX + widthHalf,
          bottom);
    }
    return tempRect;
  }

  /// 解析结束坐标文本绘制的范围
  @protected
  Rect parseEndIndexRect(
    C chart,
    BaseXAxis xAxis,
    TextPainter textPaint,
    double maxWidth,
    double bottom,
    double end,
  ) {
    // x轴绘制起始偏移距离
    var centerX = end - xAxis.endPadding;
    var widthHalf = maxWidth / 2;
    var paddingRight = chart.chartState?.widget.padding?.right ?? 0;
    var rightWidth = xAxis.endPadding + paddingRight;

    var labelAlign = xAxis.labelAlign;
    var overAlign = xAxis.labelOverAlign;
    var textHeight = xAxis.labelHeight;

    Rect tempRect;
    // 起始点标签绘制宽度是否与中间标签宽度一致
    double maxTextWidth;
    double labelHeight;
    if (rightWidth < widthHalf) {
      maxTextWidth = widthHalf + rightWidth;
      if (labelAlign == TextAlign.center) {
        // 与轴线中心对齐,取轴线两边最小的部分宽度
        widthHalf = rightWidth;
        textPaint.layout(minWidth: widthHalf * 2, maxWidth: widthHalf * 2);
        labelHeight = textPaint.height;
        if (textPaint.computeLineMetrics().length > 1) {
          if (xAxis.labelMaxLines > 1) {
            textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
            if (textPaint.computeLineMetrics().length > 1) {
              // 居中时可用宽度和非居中可用宽度时都超出一行，此时对齐方式使用用户设置的overAlign
              textPaint.textAlign = overAlign;
              if (overAlign == TextAlign.center) {
                tempRect = Rect.fromLTRB(
                    centerX - widthHalf,
                    bottom - _maxLabelHeight(xAxis, textHeight ?? labelHeight),
                    centerX + widthHalf,
                    bottom);
              } else {
                if (textHeight == null) {
                  var width = rightWidth + maxWidth / 2;
                  textPaint.layout(minWidth: width, maxWidth: width);
                  labelHeight = textPaint.height;
                } else {
                  labelHeight = textHeight;
                }

                tempRect = Rect.fromLTRB(
                    centerX - maxWidth / 2,
                    bottom - _maxLabelHeight(xAxis, labelHeight),
                    centerX + rightWidth,
                    bottom);
              }
            } else {
              // 居中时可用宽度超出一行但是非居中可用宽度没都超出一行，
              // 此时对齐方式使用靠左对齐，因为此标签为起始标签
              textPaint.textAlign = TextAlign.left;
              if (textHeight == null) {
                var width = rightWidth + maxWidth / 2;
                textPaint.layout(minWidth: width, maxWidth: width);
                labelHeight = textPaint.height;
              } else {
                labelHeight = textHeight;
              }

              tempRect = Rect.fromLTRB(
                  centerX - maxWidth / 2,
                  bottom - _maxLabelHeight(xAxis, labelHeight),
                  centerX + rightWidth,
                  bottom);
            }
          } else {
            textPaint.textAlign = TextAlign.left;
            if (textHeight == null) {
              var width = rightWidth + maxWidth / 2;
              textPaint.layout(minWidth: width, maxWidth: width);
              labelHeight = textPaint.height;
            } else {
              labelHeight = textHeight;
            }

            tempRect = Rect.fromLTRB(
                centerX - maxWidth / 2,
                bottom - _maxLabelHeight(xAxis, labelHeight),
                centerX + rightWidth,
                bottom);
          }
        } else {
          textPaint.textAlign = labelAlign;
          tempRect = Rect.fromLTRB(
              centerX - widthHalf,
              bottom - _maxLabelHeight(xAxis, textHeight ?? labelHeight),
              centerX + widthHalf,
              bottom);
        }
      } else if (overAlign == TextAlign.center && xAxis.labelMaxLines > 1) {
        textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
        if (textPaint.computeLineMetrics().length > 1) {
          textPaint.textAlign = overAlign;
          if (rightWidth < widthHalf) {
            widthHalf = rightWidth;
          }

          if (textHeight == null) {
            var width = widthHalf * 2;
            textPaint.layout(minWidth: width, maxWidth: width);
            labelHeight = textPaint.height;
          } else {
            labelHeight = textHeight;
          }

          tempRect = Rect.fromLTRB(
              centerX - widthHalf,
              bottom - _maxLabelHeight(xAxis, labelHeight),
              centerX + widthHalf,
              bottom);
        } else {
          // 居中时可用宽度超出一行但是非居中可用宽度没都超出一行，
          // 此时对齐方式使用靠左对齐，因为此标签为起始标签
          textPaint.textAlign = labelAlign;
          tempRect = Rect.fromLTRB(
              centerX - widthHalf,
              bottom - _maxLabelHeight(xAxis, textHeight ?? textPaint.height),
              centerX + rightWidth,
              bottom);
        }
      } else {
        textPaint.textAlign = xAxis.labelAlign;
        if (xAxis.labelMaxLines > 1 && overAlign != labelAlign) {
          textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
          labelHeight = textHeight ?? textPaint.height;
          if (textPaint.computeLineMetrics().length > 1) {
            textPaint.textAlign = overAlign;
          }
        } else if (textHeight == null) {
          textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
          labelHeight = textPaint.height;
        } else {
          labelHeight = textHeight;
        }

        tempRect = Rect.fromLTRB(
            centerX - widthHalf,
            bottom - _maxLabelHeight(xAxis, labelHeight),
            centerX + rightWidth,
            bottom);
      }
    } else {
      maxTextWidth = maxWidth;
      textPaint.textAlign = xAxis.labelAlign;
      if (xAxis.labelMaxLines > 1 && overAlign != labelAlign) {
        textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
        labelHeight = textHeight ?? textPaint.height;
        if (textPaint.computeLineMetrics().length > 1) {
          textPaint.textAlign = overAlign;
        }
      } else if (textHeight == null) {
        textPaint.layout(minWidth: maxTextWidth, maxWidth: maxTextWidth);
        labelHeight = textPaint.height;
      } else {
        labelHeight = textHeight;
      }

      tempRect = Rect.fromLTRB(
          centerX - widthHalf,
          bottom - _maxLabelHeight(xAxis, labelHeight),
          centerX + widthHalf,
          bottom);
    }
    return tempRect;
  }

  double _maxLabelHeight(BaseXAxis axis, double height) {
    if (height < axis.labelMinHeight) {
      return axis.labelMinHeight;
    } else if (axis.labelMaxHeight == null || height < axis.labelMaxHeight!) {
      return height;
    } else {
      return axis.labelMaxHeight!;
    }
  }
}

class DrawInfo {
  String label;
  double left;
  double right;
  double height;
  double textMaxWidth;
  TextAlign textAlign;
  double xIndex;

  DrawInfo(this.label, this.left, this.right, this.height, this.textMaxWidth,
      this.textAlign, this.xIndex);
}
